package Baza;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedList;
import java.util.List;

import Aktorzy.*;
import Budynek.*;
import Leki.*;


public class BazaDanych {

	public static final String DRIVER = "org.sqlite.JDBC";  // sterownik bazy danych
	public static final String DB_URL = "jdbc:sqlite:apteka.db"; 
	
	private Connection connection;
	private Statement stat; // zapytania
	
	public BazaDanych(){
		try{
			Class.forName(BazaDanych.DRIVER);
		} catch (ClassNotFoundException e){
			System.err.println("Brak sterownika JDBC");
			e.printStackTrace();
		}
		
		try {
			connection = DriverManager.getConnection(DB_URL);
			stat = connection.createStatement();
		} catch (SQLException e) {
			System.err.println("Problem otwarcia polaczenia z baza");
			e.printStackTrace();
		}
		
		createTables();
		
	}
	
	/**
	 * Metoda tworzy tabele dla bazy danych
	 * @return powodzenie dodania tabel do bazy
	 */
	
	public boolean createTables() {
		String createFarmaceuta = "CREATE TABLE IF NOT EXISTS farmaceuta (id INTEGER PRIMARY KEY AUTOINCREMENT, imie varchar(255) NOT NULL, nazwisko varchar(255) NOT NULL, pesel int NOT NULL, adres varchar(255) NOT NULL, email varchar(255), login varchar(255) NOT NULL, haslo varchar(255) NOT NULL, stanowisko varchar(255))";
		String createKlient = "CREATE TABLE IF NOT EXISTS klient (id INTEGER PRIMARY KEY AUTOINCREMENT, imie varchar(255) NOT NULL,  nazwisko varchar(255) NOT NULL, pesel int NOT NULL, adres varchar(255) NOT NULL, email varchar(255), login varchar(255) NOT NULL, haslo varchar(255) NOT NULL)";
		String createApteka = "CREATE TABLE IF NOT EXISTS apteka (numer_apteki INTEGER PRIMARY KEY AUTOINCREMENT, idLeku int, ilosc_lekow int(4))";
		String createMagazyn = "CREATE TABLE IF NOT EXISTS magazyn (numer_magazynu INTEGER PRIMARY KEY AUTOINCREMENT, idLeku int, ilosc_lekow int(4))";
		String createLeki = "CREATE TABLE IF NOT EXISTS leki (id_leku INTEGER PRIMARY KEY AUTOINCREMENT, sciezka_do_pliku varchar(255) NOT NULL, nazwa_leku varchar(255) NOT NULL, recepta varchar(25), cena float(3) NOT NULL, data_waznosci int NOT NULL, opis varchar(255))";
		try{
			stat.execute(createFarmaceuta);
			stat.execute(createKlient);
			stat.execute(createApteka);
			stat.execute(createMagazyn);
			stat.execute(createLeki);
		} catch (SQLException e){
			System.err.println("Blad przy tworzeniu bazy danych");
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	/**
	 * Metoda zamykająca połączenie z bazą danych
	 */
	
	public void closeConnection() {
		try {
			connection.close();
		} catch (SQLException e) {
			System.err.println("Wystapil problem w casie zamkniecia polaczenia z baza danych");
			e.printStackTrace();
		}
	}
	
	/*
	 * Metody dodające wpisy do tabel bazy danych
	 */
	public boolean insertFarmaceuta(String imie, String nazwisko, Long pesel,String adres,String email,String login, String haslo,String stanowisko) {
		try{
			PreparedStatement prepStmt = connection.prepareStatement("INSERT INTO farmaceuta VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?);");
			prepStmt.setString(1, imie);
			prepStmt.setString(2, nazwisko);
			prepStmt.setLong(3, pesel);
			prepStmt.setString(4, adres);
			prepStmt.setString(5, email);
			prepStmt.setString(6, login);
			prepStmt.setString(7, haslo);
			prepStmt.setString(8, stanowisko);
			prepStmt.execute();
		} catch (SQLException e){
			System.err.println("Blad przy wstawianiu farmaceuty do bazy");
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	public boolean insertKlient(String imie, String nazwisko, Long pesel,String adres,String email,String login, String haslo) {
		try {
			PreparedStatement prepStmt = connection.prepareStatement("INSERT INTO klient VALUES (NULL, ?, ?, ?, ?, ?, ?, ?);");
			prepStmt.setString(1, imie);
			prepStmt.setString(2, nazwisko);
			prepStmt.setLong(3, pesel);
			prepStmt.setString(4, adres);
			prepStmt.setString(5, email);
			prepStmt.setString(6, login);
			prepStmt.setString(7, haslo);
			prepStmt.execute();
		} catch (SQLException e) {
			System.err.println("Blad przy dodawaniu klienta do bazy danych");
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	public boolean insertApteka(Integer idLeku, Integer iloscLekow) {
		try{
			PreparedStatement prepStmt = connection.prepareStatement("INSERT INTO apteka VALUES (NULL, ?, ?);");
			prepStmt.setInt(1, idLeku);
			prepStmt.setInt(2, iloscLekow);
			prepStmt.execute();
		}catch (SQLException e){
			System.err.println("Blad przy dodawaniu rekordu dot. apteki");
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	public boolean insertMagazyn(Integer idLeku, Integer iloscLekow){
		try {
			PreparedStatement prepStmt = connection.prepareStatement("INSERT INTO magazyn VALUES (NULL, ?, ?);");
			prepStmt.setInt(1, idLeku);
			prepStmt.setInt(2, iloscLekow);
			prepStmt.execute();
		} catch (SQLException e) {
			System.err.println("Blad przy dodawaniu rekordu dot. magazynu");
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	public boolean insertLeki(String sciezka, String nazwaLeku, String recepta,Double cena, String dataWaznosci,String opis) {
		try {
			PreparedStatement prepStmt = connection.prepareStatement("INSERT INTO leki VALUES(NULL, ?, ?, ?, ?, ?, ?);");
			prepStmt.setString(1, sciezka);
			prepStmt.setString(2, nazwaLeku);
			prepStmt.setString(3, recepta);
			prepStmt.setDouble(4, cena);
			prepStmt.setString(5, dataWaznosci);
			prepStmt.setString(6, opis);
			prepStmt.execute();
		} catch (SQLException e) {
			System.err.println("Blad przy dodawaniu rekordu dot. Leku");
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	/*
	 * Metody odczytujące dane z bazy
	 */
	
	public List<Farmaceuta> selectFarmaceuta(){
		List<Farmaceuta> farmaceuci = new LinkedList<Farmaceuta>();
		try {
			ResultSet result = stat.executeQuery("SELECT * FROM farmaceuta");
			Integer id;
			String imie ;
			String nazwisko ;
			Long pesel ;
			String adres ;
			String email ;
			String login ;
			String haslo ;
			String stanowisko;
			while(result.next()){
				id = result.getInt("id");
				imie = result.getString("imie");
				nazwisko = result.getString("nazwisko");
				pesel = result.getLong("pesel");
				adres = result.getString("adres");
				email = result.getString("email");
				login = result.getString("login");
				haslo = result.getString("haslo");
				stanowisko = result.getString("stanowisko");
				farmaceuci.add(new Farmaceuta(id, imie, nazwisko, pesel, adres, email, login, haslo, stanowisko));
			}
			
		} catch (SQLException e) {
			System.err.println("Blad w czasie odczytu farmaceutow z bazy");
			e.printStackTrace();
			return null;
		}
		return farmaceuci;
	}
	
	public Farmaceuta selectFarmaceuta(String LOGIN){
		Farmaceuta farmaceuta = null;
		try {
			ResultSet result = stat.executeQuery("SELECT * FROM farmaceuta WHERE login='"+LOGIN+"'");
			Integer id;
			String imie ;
			String nazwisko ;
			Long pesel ;
			String adres ;
			String email ;
			String login ;
			String haslo ;
			String stanowisko;
			while(result.next()){
				id = result.getInt("id");
				imie = result.getString("imie");
				nazwisko = result.getString("nazwisko");
				pesel = result.getLong("pesel");
				adres = result.getString("adres");
				email = result.getString("email");
				login = result.getString("login");
				haslo = result.getString("haslo");
				stanowisko = result.getString("stanowisko");
				farmaceuta = new Farmaceuta(id, imie, nazwisko, pesel, adres, email, login, haslo, stanowisko);
			}
			
		} catch (SQLException e) {
			System.err.println("Blad w czasie odczytu farmaceutow z bazy");
			e.printStackTrace();
			return null;
		}
		
		return farmaceuta;
	}
	
	public List<Klient> selectKlient(){
		List<Klient> klienci = new LinkedList<Klient>();
		try{
			ResultSet result = stat.executeQuery("SELECT * FROM klient");
			Integer id;
			String imie ;
			String nazwisko ;
			Long pesel ;
			String adres ;
			String email ;
			String login ;
			String haslo ;
			while(result.next()){
				id = result.getInt("id");
				imie = result.getString("imie");
				nazwisko = result.getString("nazwisko");
				pesel = result.getLong("pesel");
				adres = result.getString("adres");
				email = result.getString("email");
				login = result.getString("login");
				haslo = result.getString("haslo");
				klienci.add(new Klient(id, imie, nazwisko, pesel, adres, email, login, haslo));
			}
		} catch (SQLException e) {
			System.err.println("Blad w czasie odczytu klientow z bazy");
			e.printStackTrace();
			return null;
		}
		return klienci;
	}
	
	public Klient selectKlient(String LOGIN){
		Klient klient = null;
		try{
			ResultSet result = stat.executeQuery("SELECT * FROM klient WHERE login='"+LOGIN+"'");
			Integer id;
			String imie ;
			String nazwisko ;
			Long pesel ;
			String adres ;
			String email ;
			String login ;
			String haslo ;
			while(result.next()){
				id = result.getInt("id");
				imie = result.getString("imie");
				nazwisko = result.getString("nazwisko");
				pesel = result.getLong("pesel");
				adres = result.getString("adres");
				email = result.getString("email");
				login = result.getString("login");
				haslo = result.getString("haslo");
				klient = new Klient(id, imie, nazwisko, pesel, adres, email, login, haslo);
			}
		} catch (SQLException e) {
			System.err.println("Blad w czasie odczytu klientow z bazy");
			e.printStackTrace();
			return null;
		}
		return klient;
	}
	
	public List<Apteka> selectApteka() {
		List<Apteka> apteka = new LinkedList<Apteka>();
		try{
			ResultSet result = stat.executeQuery("SELECT * FROM apteka");
			Integer idLeku;
			Integer numer_apteki;
			Integer iloscLekow;
			while(result.next()){
				numer_apteki = result.getInt("numer_apteki");
				idLeku = result.getInt("idLeku");
				iloscLekow = result.getInt("ilosc_lekow");
				apteka.add(new Apteka(numer_apteki, idLeku, iloscLekow));
			}
		} catch (SQLException e) {
			System.err.println("Blad w czasie odczytu rekordow dot. apteki z bazy");
			e.printStackTrace();
			return null;
		}
		return apteka;
	}
	
	public List<Magazyn> selectMagazyn() {
		List<Magazyn> magazyn = new LinkedList<Magazyn>();
		try{
			ResultSet result = stat.executeQuery("SELECT * FROM magazyn");
			Integer numerMagazynu ;
			Integer idLeku ;
			Integer iloscLekow ;
			while(result.next()){
				numerMagazynu = result.getInt("numer_magazynu");
				idLeku = result.getInt("idLeku");
				iloscLekow = result.getInt("ilosc_lekow");
				magazyn.add(new Magazyn(numerMagazynu, idLeku, iloscLekow));
			}
		} catch (SQLException e) {
			System.err.println("Blad w czasie odczytu rekordow dot. magazynu z bazy");
			e.printStackTrace();
			return null;
		}
		return magazyn;
	}
	
	public List<Leki> selectLeki() {
		List<Leki> leki= new LinkedList<Leki>();
		try{
			ResultSet result = stat.executeQuery("SELECT * FROM leki");
			Integer idLeku ;
			String nazwaLeku ;
			String recepta ;
			Double cena ;
			String dataWaznosci ;
			String sciezka;
			String opis ;
			while(result.next()){
				idLeku = result.getInt("id_leku");
				sciezka = result.getString("sciezka_do_pliku");
				nazwaLeku = result.getString("nazwa_leku");
				recepta = result.getString("recepta");
				cena = result.getDouble("cena");
				dataWaznosci = result.getString("data_waznosci");
				opis = result.getString("opis");
				leki.add(new Leki(idLeku, sciezka, nazwaLeku, recepta, cena, dataWaznosci, opis));
			}
		} catch (SQLException e) {
			System.err.println("Blad w czasie odczytu rekordow dot. magazynu z bazy");
			e.printStackTrace();
			return null;
		}
		return leki;
	}
	
	/**
	 * Metoda sprawdzająca czy dany login istnieje w bazie
	 * @param login Wyszukiwany login
	 * @param pracownik Flaga oznaczająca pracownika (true=pracownik/false=klient)
	 * @return Czy znaleziono osobę o podanym loginie
	 */
	
	public Boolean checkLogin(String login, Boolean pracownik){
		String SQL;
		if(pracownik == true){
			SQL = "SELECT * FROM farmaceuta WHERE login='"+login+"'";
		}else{
			SQL = "SELECT * FROM klient WHERE login='"+login+"'";
		}
		try{
			ResultSet result = stat.executeQuery(SQL);
			if(result.next()){
				return true;
			}
		}catch(SQLException e){
			System.err.println("Błąd pobrania loginu z bazy danych");
			e.printStackTrace();
		}
		return false;
	}
	
	public Boolean checkLogin(String login, String haslo, Boolean pracownik){
		String SQL;
		if(pracownik == true){
			SQL = "SELECT * FROM farmaceuta WHERE login='"+login+"' AND haslo='"+haslo+"'";
		}else{
			SQL = "SELECT * FROM klient WHERE login='"+login+"' AND haslo='"+haslo+"'";
		}
		try{
			ResultSet result = stat.executeQuery(SQL);
			if(result.next()){
				return true;
			}
		}catch(SQLException e){
			System.err.println("Błąd przy sprawdzeniu danych w bazie");
			e.printStackTrace();
		}
		return false;
	}
	
	/**
	 * Metoda sprawdza czy w bazie jest wymieniony pesel
	 * @param pesel
	 * @param pracownik Flaga oznaczająca pracownika (true=pracownik/false=klient)
	 * @return Czy znaleziono podany numer pesel
	 */
	public Boolean checkPesel(Long pesel, Boolean pracownik){
		String SQL;
		if(pracownik == true){
			SQL = "SELECT * FROM farmaceuta WHERE pesel='"+pesel.toString()+"'";
		}else{
			SQL = "SELECT * FROM klient WHERE pesel='"+pesel.toString()+"'";
		}
		try{
			ResultSet result = stat.executeQuery(SQL);
			if(result.next()){
				return true;
			}
		}catch(SQLException e){
			System.err.println("Błąd przy sprawdzeniu danych w bazie");
			e.printStackTrace();
		}
		return false;
	}
	
	/**
	 * Metoda usuwa uzytkownika z bazy danych
	 * @param login Login uzytkownika
	 * @param pracownik Flaga pracownika (true=uzytkownik jest pracownikiem / false=uzytkownik jest klientem)
	 * @return true=powodzenie usuniecia / false=niepowodzenie
	 */
	public Boolean usunKonto(String login, Boolean pracownik){
		String SQL;
		if(pracownik == true){
			SQL = "DELETE FROM farmaceuta WHERE login='"+login+"'";
		}else{
			SQL = "DELETE FROM klient WHERE login='"+login+"'";
		}
		try{
			PreparedStatement prepStmt = connection.prepareStatement(SQL);
			prepStmt.execute();
		}catch(SQLException e){
			System.err.println("Błąd przy sprawdzeniu danych w bazie");
			e.printStackTrace();
			return false;
		}
		return true; 
	}
	
	/**
	 * Metoda zmienia haslo uzytkownika
	 * @param login
	 * @param haslo
	 * @param pracownik
	 * @return
	 */
	public Boolean changePassword(String login, String stare_haslo, String nowe_haslo, Boolean pracownik){
		String SQL;
		if(pracownik == true){
			SQL = "UPDATE farmaceuta SET haslo='"+nowe_haslo+"' WHERE login='"+login+"'";
		}else{
			SQL = "UPDATE klient SET haslo='"+nowe_haslo+"' WHERE login='"+login+"'";
		}
		try{
			if(checkLogin(login, stare_haslo, pracownik)){
				PreparedStatement prepStmt = connection.prepareStatement(SQL);
				prepStmt.execute();
			}
			else{
				return false;
			}
		}catch(SQLException e){
			System.err.println("Błąd przy sprawdzeniu danych w bazie");
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	/**
	 * Metoda zmienia ilosc lekow dla podanego numeru apteki
	 * @param numer_apteki
	 * @param ilosc_lekow
	 * @return
	 */
	public Boolean changeApteka(Integer numer_apteki, Integer ilosc_lekow){
		String SQL = "UPDATE apteka SET ilosc_lekow='"+ilosc_lekow+"' WHERE numer_apteki='"+numer_apteki+"'";
		try{
			PreparedStatement prepStmt = connection.prepareStatement(SQL);
			prepStmt.execute();
		}catch(SQLException e){
			System.err.println("Błąd przy sprawdzeniu danych w bazie");
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	/**
	 * Metoda zmienia ilosc danego leku w magazynie
	 * @param numer_magazynu
	 * @param ilosc_lekow
	 * @return
	 */
	public Boolean changeMagazyn(Integer numer_magazynu, Integer ilosc_lekow){
		String SQL = "UPDATE magazyn SET ilosc_lekow='"+ilosc_lekow+"' WHERE numer_magazynu='"+numer_magazynu+"'";
		try{
			PreparedStatement prepStmt = connection.prepareStatement(SQL);
			prepStmt.execute();
		}catch(SQLException e){
			System.err.println("Błąd przy sprawdzeniu danych w bazie");
			e.printStackTrace();
			return false;
		}
		return true;
	}
}
